package k2_oop.p9_collection.demo03;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
import java.util.Scanner;

/**
 * @Author lixinlei
 * @Date 2025/1/20 14:52
 */
public class RedPacket {

    //初始化两个工具对象，用于控制台输入和做随机抢红包
    Scanner scanner = new Scanner(System.in);
    Random random = new Random();

    //初始化剩余的金额和红包的数量
    public double remainMoney;
    public int redPacketCount;

    //初始化每个人可以抢到的金额的最大值和最小值
    public double money_min = 0.01;
    public double money_max;

    //红包的超时时间
    public LocalDateTime overTime;

    //初始化一个ArrayList，用于存放所有的抢到的红包信息
    //方便后面展示使用和用于判断某人是否重复抢红包的依据
    public ArrayList<RedPacketInfo> redPacketInfos = new ArrayList<>();


    /**
     * 发送红包
     */
    public void sendRedPacket(){

        System.out.println("大家请注意，开始发红包了！！！！");

        do{
            System.out.println("款爷，请输入要发送的金额：");
            //尝试输出发送的红包金额，并转成Double类型
            try {
                remainMoney = Double.parseDouble(scanner.nextLine());
                //如果金额超过200或小于等于0，给提示，重新输入
                if(remainMoney>200 || remainMoney<=0){
                    System.out.println("金额的范围在0.01-200,请重新输入");
                }
            }catch (Exception e){
                //如果输入的内容不是数字，catch捕获异常，给提示，重新输入
                System.out.println("请输入正确的金额");
            }
        }while (remainMoney>200 || remainMoney<=0);

        do{
            System.out.println("款爷，请输入要发送的红包数量：");
            //尝试输出发送的红包金额，并转成Double类型
            try {

                redPacketCount = Integer.parseInt(scanner.nextLine());
                //假定发了5元钱，每个0.01元，最多能发 5/0.01=500个红包
                //所以最多能发的数量为 remainMoney*100
                if(redPacketCount>remainMoney*100 || redPacketCount<=0){
                    System.out.println("数量要大于0且保证每个红包至少有0.01元,请重新输入");
                }
            }catch (Exception e){
                //如果输入的内容不是数字，catch捕获异常，给提示，重新输入
                System.out.println("请输入正确的数量");
            }
        }while (redPacketCount>remainMoney*100 || redPacketCount<=0);

        //规定每个人最多能抢到的金额是平均值的1.5倍
        money_max = (remainMoney/redPacketCount) * 1.5;

        //发送红包的那个时刻的时间
        LocalDateTime currentTime = LocalDateTime.now();
        //以发送红包的时间加1天为抢红包的超时时间
        overTime = currentTime.plusDays(1);
//        overTime = currentTime.plusSeconds(10);

        System.out.println("红包发送完毕！！！");
    }


    /**
     * 抢红包的方法
     */
    public void getRedPacket(){

        //循环执行抢红包的方法，直到返回值出现false直接终止执行
        while(true){
            if (!getRedPacketDetail()) {
                break;
            }
        }
    }

    /**
     * 抢红包的具体执行内容
     *  1.有红包
     *  2.没超时
     *  3.不重复
     */
    public boolean getRedPacketDetail(){

        //初始化表示是true，表示可以继续抢红包，如果有任何的特殊情况(红包派发完毕，超时，。。。)可以把true置为false
        boolean flag = true;

        //抢红包的那个时刻的时间
        LocalDateTime currentTime = LocalDateTime.now();

        //1.如果抢红包的时间早于超时时间，就可以继续
        if(currentTime.isBefore(overTime)){

            //输入姓名开始抢红包
            System.out.println("请输入姓名:");
            String getRedPacketName = scanner.nextLine();

            //初始化一个RedPacketInfo的对象，用于判断输入的姓名是否应抢过红包
            RedPacketInfo redPacketInfo = new RedPacketInfo();
            redPacketInfo.setName(getRedPacketName);

            //2.如果此人没抢过红包，可以继续
            if(!redPacketInfos.contains(redPacketInfo)){

                double tempMoney = 0;

                //如果红包数量减1后等于0，表示为最后一个红包
                if(--redPacketCount==0){
                    tempMoney = remainMoney;
                }else{
                    do{
                        //先为此人随机一个金额，如果金额不在上限与下限范围内，重新随机，直到在范围内为止
                        tempMoney = random.nextDouble()*remainMoney;
                    }while (tempMoney<money_min || tempMoney>money_max);
                }

                //输出此人抢到红包的信息
                System.out.println(getRedPacketName+"在"+transformDateTime(currentTime)+"抢到了 "+ transformDouble(tempMoney) +" 元");

                //把此人抢到的红包信息封装为对象，添加到列表中，以方便后续判断人员是否重复
                redPacketInfos.add(new RedPacketInfo(getRedPacketName,transformDouble(tempMoney),transformDateTime(currentTime)));

                //剩余金额=原剩余金额-此次已经抢走的金额
                remainMoney-=tempMoney;

                //如果最后一个红包已经抢完，终止执行
                if(redPacketCount==0){
                    System.out.println("红包已经派发完毕,是否查看结果？[Y/N]");

                    String resultFlag = scanner.nextLine();

                    switch (resultFlag.toLowerCase()){
                        case "y":
                            Collections.sort(redPacketInfos);
                            System.out.println(redPacketInfos);
                            System.out.println("手气最佳："+redPacketInfos.get(0));
                        case "n":
                            break;
                        default:
                            System.out.println("请输入Y或N");
                    }
                    flag = false;
                }
            }else {
                System.out.println(getRedPacketName+" 你脸怎么这么大呢");
            }
        }else{
            System.out.println("你来晚了,已经超时了");
            flag = false;
        }

        return flag;
    }

    /**
     * 把 LocalDateTime / LocalDate / LocalTime 类型进行标准化返回
     * @param dateTime
     * @return
     */
    public String transformDateTime(Object dateTime){

        if(dateTime instanceof LocalDateTime){
            return ((LocalDateTime)dateTime).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        }else if(dateTime instanceof LocalDate){
            return ((LocalDate)dateTime).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        }else if(dateTime instanceof LocalTime){
            return ((LocalTime)dateTime).format(DateTimeFormatter.ofPattern("HH:mm:ss"));
        }
        return "";
    }

    /**
     * 把Double类型的值，四舍五入后保留两位小数返回
     * @param num
     * @return
     */
    public double transformDouble(double num){
        BigDecimal bigDecimal = new BigDecimal(num);
        bigDecimal = bigDecimal.setScale(2, RoundingMode.HALF_UP);
        return bigDecimal.doubleValue();
    }
}
